package com.IntelligenceInsight.Myth.controller;

import com.IntelligenceInsight.Myth.service.JobService;
import com.IntelligenceInsight.Myth.service.JobMgrService;
import com.IntelligenceInsight.Myth.service.ModelService;
import com.IntelligenceInsight.Myth.util.NoteRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@RestController
public class JobController {
    private static String algorithmUrl = "http://127.0.0.1:5000/";
    @Autowired
    private JobService service;
    @Autowired
    private ModelService modelService;
    @Autowired
    private JobMgrService jobMgrService;

    @RequestMapping(value = {"/getJobListAll.do"}, method = RequestMethod.POST)
    public NoteRequest JobListAll(HttpServletRequest request) {
        int page = Integer.parseInt(request.getParameter("page"));
        int limit = Integer.parseInt(request.getParameter("limit"));
        int count=service.JobListAllCount();
        int page_temp = page;
        int limit_temp = limit;
        if (count < page * limit) {
            limit = count - (page - 1) * limit;
        }
        page = (page_temp - 1) * limit_temp;
        NoteRequest res = service.JobListAll(page,limit);
        res.setCount(count);
        return res;
    }

    @RequestMapping(value = {"/getJobListByOwner.do"}, method = RequestMethod.POST)
    public NoteRequest JobListByOwner(HttpServletRequest request) {
        String owner = request.getParameter("owner");
        NoteRequest res = service.JobListByOwner(owner);
        return res;
    }

    @RequestMapping(value = {"/getJobListMine.do"}, method = RequestMethod.POST)
    public NoteRequest JobListMine(HttpServletRequest request) {
        String owner = request.getSession().getAttribute("username").toString();
        NoteRequest res = service.JobListByOwner(owner);
        return res;
    }


    @RequestMapping(value = {"/getJobByUuid.do"}, method = RequestMethod.POST)
    public NoteRequest JobByUuid(HttpServletRequest request) {
        String uuid = request.getParameter("uuid");
        NoteRequest res = service.JobByUuid(uuid);
        return res;
    }


    @RequestMapping(value = {"/getJobByName.do"}, method = RequestMethod.POST)
    public NoteRequest JobByName(HttpServletRequest request) {
        String name = request.getParameter("name");
        NoteRequest res = service.JobByName(name);
        return res;
    }


//    @RequestMapping(value = {"/getJobByModel.do"}, method = RequestMethod.POST)
//    public NoteRequest JobByModel(HttpServletRequest request) {
//        String modelUuid = request.getParameter("model");
//        NoteRequest res = service.JobByModel(modelUuid);
//        return res;
//    }

    @RequestMapping(value = {"/getJobByModel.do"}, method = RequestMethod.POST)
    public NoteRequest JobByModel(HttpServletRequest request) {
        String model = request.getParameter("model");
        NoteRequest res = service.JobByModel(model);
        return res;
    }

    @RequestMapping(value = {"/jobAdd.do"}, method = RequestMethod.POST)
    public NoteRequest JobAdd(HttpServletRequest request) {
        String model = request.getParameter("model");
        String dataset = request.getParameter("dataset");
        String params = request.getParameter("params");
        NoteRequest res = service.JobAdd(model, dataset, params);

        new Thread(()->jobMgrService.submit(model, dataset, params)).start();

        return res;
    }

//    @RequestMapping(value = {"/jobAdd.do"}, method = RequestMethod.POST)
//    public NoteRequest JobAdd(HttpServletRequest request) {
//        String uuid = UUID.randomUUID().toString();
//        String name = request.getParameter("name");
//        String modelUuid = request.getParameter("model");
//        String owner = request.getSession().getAttribute("username").toString();
//        String filePath = request.getParameter("filePath");
//
//        SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
//        String date = df.format(new Date());
//        String resultPath = "/myth/results/" + name + "_" + date + ".txt";
//
//        NoteRequest res = new NoteRequest();
//
//        System.out.println(modelUuid);
//        // Step 1: model must be exist
//        res = modelService.ModelByUuid(modelUuid);
//        if(res.getStatus() != 0) {
//            return res;
//        }
//        Model model = (Model) res.getData();
//        String modelString = model.getModelString();
//
//        // Step 2: Job name and uuid must unique
//        res = service.JobByName(name);
//        if(res.getStatus() == 0){
//            res.setStatus(1);
//            res.setMsg("Job name is exist");
//            res.setData(null);
//            return res;
//        }
//        // TODO: If uuid is exist, should be create a new uuid and check again until uuid is unique
//        res = service.JobByUuid(uuid);
//        if(res.getStatus() == 0){
//            res.setStatus(1);
//            res.setMsg("Job uuid is exist, this operation is reasonable");
//            res.setData(null);
//            return res;
//        }
//
//        // Step 3: persist job info into database
//        res = service.JobAdd(uuid, name, modelUuid, owner, filePath, resultPath);
//
//
//        // Step 4: Submit job to Computing background
//        // TODO: Every job create a thread is not good. Better way is just one thread check submit
//        // TODO: queue and submit job, in addition, another thread to listen job status change.
//        new Thread(()->jobMgrService.submitQueue(uuid, modelUuid, modelString, filePath, resultPath)).start();
//
//        return res;
//    }

    @RequestMapping(value = {"/JobRemoveByuuid.do"}, method = RequestMethod.POST)
    public NoteRequest ModelRemoveByName(HttpServletRequest request) {
        NoteRequest res = new NoteRequest();
        String uuid = request.getParameter("uuid");
        res = service.JobDelete(uuid);
        return res;
    }

    @PostMapping(value={"/showFile"})
    public NoteRequest ShowFile(HttpServletRequest request){

        NoteRequest res = new NoteRequest();

        File file1 = new File("ml\\data");
        String[] list = file1.list();
        if(list!=null){
            res.setStatus(0);
            res.setMsg("success");
            res.setData(list);
        }else{
            res.setStatus(1);
            res.setMsg("failure");
        }

        return res;

    }

    @PostMapping(value={"/showData"})
    public NoteRequest ShowData(HttpServletRequest request){

        NoteRequest res = new NoteRequest();

        String name = request.getParameter("name");
        File file = new File("ml\\data"+name);
        FileReader fr = null;
        BufferedReader br = null;
        ArrayList<String> arrayList = null;
        String[] strings = null;
        try {
            fr = new FileReader(file);
            br = new BufferedReader(fr);

            arrayList = new ArrayList<>();
            String str;

            while((str=br.readLine())!=null){
                arrayList.add(str);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            try {
                br.close();
                fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        strings = new String[arrayList.size()];
        for(int i=0;i<arrayList.size();i++){
            strings[i] = arrayList.get(i);
        }
        for(String s: strings) {
            System.out.println(s);
        }

        if(strings!=null) {
            res.setStatus(0);
            res.setMsg("success");
            res.setData(strings);
        }else{
            res.setStatus(1);
            res.setMsg("failure");
        }
        return res;
    }


    @PostMapping(value={"/featureSelect"})
    public NoteRequest FeatureSelect(HttpServletRequest request)  {

        NoteRequest res = new NoteRequest();

        String index = request.getParameter("index");
        String name = request.getParameter("name");

        File file = new File("ml\\data"+name);
        File file2 = new File("ml\\data"+"test1");
        FileReader fr = null;
        BufferedReader br = null;
        FileWriter fw = null;
        BufferedWriter bw = null;
        try{

            if(!file2.exists()){
                file2.createNewFile();
            }

            ArrayList<String> arrayList = null;
            String[] strings = null;

            fr = new FileReader(file);
            br = new BufferedReader(fr);
            fw = new FileWriter(file2);
            bw = new BufferedWriter(fw);

            String[] indexs = index.split(" ");
            int[] ids = new int[indexs.length];
            for(int i=0;i<ids.length;i++){
                ids[i] = Integer.parseInt(indexs[i]);
            }

            String str;
            String s = "";
            String[] strs = null;

            while((str=br.readLine())!=null) {
                StringBuffer sb = new StringBuffer("");

                if (str.indexOf(" ") == -1) {
                    strs = str.split(",");
                } else {
                    strs = str.split("\\,*" + "\\s+");
                }

                for (int i = 0; i < ids.length; i++) {
                    s += strs[ids[i]];
                    if (i != (ids.length - 1)) {
                        s += ", ";
                    }
                }
                sb.append(s + "\n");

                bw.write(sb.toString());
                s = "";
            }
            res.setStatus(0);
            res.setMsg("success");
            res.setData(file2.getName());
        }catch(Exception e){
            res.setStatus(1);
            res.setMsg("failure");
            e.printStackTrace();
        }finally {
            try{
                bw.close();
                fw.close();
                br.close();
                fr.close();
            }catch(Exception e){
                e.printStackTrace();
            }
        }



        return res;
    }


    // 第一步：解析前端传过来的参数，并构造POST请求
    // 第二步：向算法服务（python后端：algorithmUrl = http://127.0.0.1:5000/）发起请求，获取算法执行结果
    // 第三步：将算法服务返回的结果解析为JSON格式（或键值对形式），返回给前端，用于绘图展示
    // TODO 1、配合前端同学解析参数，构造请求体
    // TODO 2、将结果返回给前端，配合前端进行绘图
    // TODO 3、将整个流程走通
    @RequestMapping(value = {"/algorithm.do"}, method = RequestMethod.POST)
    public NoteRequest algorithm(HttpServletRequest request) throws IOException {
        // 第一步：解析前端传过来的参数，并构造POST请求
        String model = request.getParameter("model");
        String dataset = request.getParameter("dataset");

        URL url = new URL(algorithmUrl + "algorithm");
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        conn.setConnectTimeout(20 * 1000);
        conn.setRequestMethod("POST");
        conn.setDoOutput(true);
        conn.setDoInput(true);
        byte[] postDataBytes = ("{\"model\" : \"" + model + "\", \"dataset\" : \"" + dataset + "\"}").getBytes();  //请求体传入{"a" : "b"}这样一个键值对
        conn.getOutputStream().write(postDataBytes);

        // 第二步：向算法服务（python后端）发起请求，获取结果
        BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
        StringBuilder buffer = new StringBuilder();
        String line;
        while ((line = in.readLine()) != null) {
            buffer.append(line);
        }

        // 第三步：将算法服务返回的结果解析为JSON格式（或键值对形式），返回给前端，用于绘图展示
        NoteRequest res = new NoteRequest();
        if (HttpServletResponse.SC_OK == conn.getResponseCode()) {
            String responseStr = buffer.length() > 0 ? buffer.toString() : "{}";
            JSONObject json = JSON.parseObject(responseStr);
            System.out.println(json);
            res.setData(json);
        }

        in.close();
        conn.disconnect();

        return res;
    }

    // 返回数据集信息
    // TODO 前端展示数据元信息
    @RequestMapping(value = {"/statistic.do"}, method = RequestMethod.POST)
    public NoteRequest statistic(HttpServletRequest request) throws IOException {
        // 第一步：解析前端传过来的参数，并构造POST请求
        String dataset = request.getParameter("dataset");

        URL url = new URL(algorithmUrl + "statistic");
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        conn.setConnectTimeout(20 * 1000);
        conn.setRequestMethod("POST");
        conn.setDoOutput(true);
        conn.setDoInput(true);
        byte[] postDataBytes = ("{\"dataset\" : \"" + dataset + "\"}").getBytes();  //请求体传入{"a" : "b"}这样一个键值对
        conn.getOutputStream().write(postDataBytes);

        // 第二步：向算法服务（python后端）发起请求，获取结果
        BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
        StringBuilder buffer = new StringBuilder();
        String line;
        while ((line = in.readLine()) != null) {
            buffer.append(line);
        }

        // 第三步：将算法服务返回的结果解析为JSON格式（或键值对形式），返回给前端，用于绘图展示
        NoteRequest res = new NoteRequest();
        if (HttpServletResponse.SC_OK == conn.getResponseCode()) {
            String responseStr = buffer.length() > 0 ? buffer.toString() : "{}";
            JSONObject json = JSON.parseObject(responseStr);
            System.out.println(json);
            res.setData(json);
        }

        in.close();
        conn.disconnect();

        return res;
    }
}
